﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;

namespace FlightSearchServer
{
    class CacheOperationInvoker : IOperationInvoker
    {
        private IOperationInvoker invoker;

        public CacheOperationInvoker(IOperationInvoker invoker)
        {
            this.invoker = invoker;
        }


        public bool IsSynchronous 
        {
            get
            {
                return invoker.IsSynchronous;
            }
        }


        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            string key = "&";

            foreach (var o in inputs)
                key += o.ToString( ) + "&";

            //CacheOutput is a custom C# class that encapsulates the output parameter array and return value
            CacheEntry item = null;
            object retval = null;
            outputs = null;
            if (!string.IsNullOrEmpty(key))
            {

                //Get from Cache
                item = GlobalResultsCache.Instance.getCacheEntry(key);
                if (item != null)
                {
                    //return from Cache
                    retval = item.RetVal;
                    outputs = item.Outputs;
                }
                else
                {
                    //Invoke the method using default invoker instance and set values in cache.
                    retval = invoker.Invoke(instance, inputs, out outputs);
                    item = new CacheEntry();
                    item.RetVal = (FlightRoutes)retval;
                    if (item.RetVal.Count == 0)
                        return retval;
                    item.Outputs = outputs;
                    GlobalResultsCache.Instance.addCacheEntry( key, (CacheEntry)item);
                }
            }
            return retval;
        }

        public object[] AllocateInputs()
        {
            return invoker.AllocateInputs();
        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            return invoker.InvokeBegin(instance, inputs, callback, state);
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            return invoker.InvokeEnd( instance, out outputs, result);
        }

    }
}
